/*----------------------------------------------------------------------
 *
 * Copyright 2009, Thomas Dejanovic.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 *
 *---------------------------------------------------------------------
 *
 * Core to connect FPGA ports to the varouse modules in this design.
 *
 *---------------------------------------------------------------------*/


module s3board_core

  (/*AUTOARG*/
  // Outputs
  reset, an, ssd, led, button_in, switch_in, c3_inc, c2_inc, c1_inc,
  c0_inc,
  // Inputs
  clk50, btn, swt, led_out, c3_out, c2_out, c1_out, c0_out
  );

  //----------------------------------------
  input                 clk50;

  output                reset;
  //----------------------------------------

  //----------------------------------------
  // FPGA interface to stuff on the board.
  input [3:0]           btn;
  input [7:0]           swt;
  output [3:0]          an;
  output [7:0]          ssd;
  output [7:0]          led;
  //----------------------------------------

  //----------------------------------------
  //
  output [3:0]          button_in;
  output [7:0]          switch_in;
  input  [7:0]          led_out;

  output                c3_inc;
  output                c2_inc;
  output                c1_inc;
  output                c0_inc;

  input [3:0]           c3_out;
  input [3:0]           c2_out;
  input [3:0]           c1_out;
  input [3:0]           c0_out;
 //----------------------------------------


  /*----------------------------------------------------------------*/

  /*-AUTOUNUSED-*/

  /*AUTOINPUT*/

  /*AUTOOUTPUT*/

  /*-AUTOREGINPUT-*/

  /*AUTOREG*/

  /*AUTOWIRE*/

  /*------------------------------------------------------------------
   *
   * local definitions and connections.
   *
   * */

  wire [7:0]            led, led_out;
  assign                led = led_out;

  wire [3:0]           btn, button_in;
  assign               button_in = btn;

  wire [7:0]           swt, switch_in;
  assign               switch_in = swt;

  wire [15:0]          counter_out;
  assign               counter_out = {c3_out, c2_out, c1_out, c0_out};

  wire                 c0_inc, c1_inc, c2_inc, c3_inc;

  /*------------------------------------------------------------------
   *
   * Generate reset.
   *
   * */

  reg [7:0]            reset_count;
  initial reset_count = 8'hff;

  always @ (posedge clk50) begin
    if (btn[3]) // user reset.
      reset_count <= 8'hff;
    else
      reset_count <= reset_count - {7'd0, |reset_count};
  end

  reg reset;
  always @ (posedge clk50) begin
    reset    <= |reset_count;
  end

  /*-----------------------------------------------------------------
   *
   *
   *
   * */

  reg [27:0]            clock_div;

  initial clock_div = 28'd0;

  always @ (posedge clk50) begin
    clock_div <= clock_div + 28'd1;
  end

  /*-----------------------------------------------------------------
   *
   *
   *
   * */

  wire [3:0] an;
  assign     an = ~(1<<clock_div[19:18]);


  reg        tick_d;
  wire       tick_in;
  wire       tick;
  assign     tick = tick_in & ~tick_d;
  assign     tick_in = clock_div[22];
  always @ (posedge clk50) tick_d <= tick_in;
  assign     c3_inc = tick & swt[3];
  assign     c2_inc = tick & swt[2];
  assign     c1_inc = tick & swt[1];
  assign     c0_inc = tick & swt[0];

  wire [3:0] digit;
  assign     digit = ~an[0] ? counter_out[ 3: 0] :
                     ~an[1] ? counter_out[ 7: 4] :
                     ~an[2] ? counter_out[11: 8] :
                     counter_out[15:12];

  reg [7:0]  display;
  always @ (digit) begin
    case (digit)
      4'h0 : display <= 8'b11111100;
      4'h1 : display <= 8'b01100000;
      4'h2 : display <= 8'b11011010;
      4'h3 : display <= 8'b11110010;
      4'h4 : display <= 8'b01100110;
      4'h5 : display <= 8'b10110110;
      4'h6 : display <= 8'b10111110;
      4'h7 : display <= 8'b11100000;
      4'h8 : display <= 8'b11111110;
      4'h9 : display <= 8'b11100110;
      4'hA : display <= 8'b11101110;
      4'hb : display <= 8'b00111110;
      4'hC : display <= 8'b10011100;
      4'hd : display <= 8'b01111010;
      4'hE : display <= 8'b10011110;
      4'hF : display <= 8'b10001110;
      default : display <= 8'd0;
    endcase // case(digit)
  end // always @ (digit)

  wire [7:0] ssd;
  assign     ssd = btn[1] ? display : ~display;

  /*----------------------------------------------------------------*/

endmodule // s3board_core


// Local Variables:
// verilog-library-directories:(".")
// verilog-library-extensions:(".v")
// End:
